#include <pthread.h>
#include <ctime>
#include <unistd.h>
#include <sys/types.h>
#include <cstdlib>
#include <cstring>
#include <vector>
#include "QueueBlock.hpp"
#include "Task.hpp"
#define PRODUCTOR_NUMBER 3
#define CONSUER_NUMBER 2
std::string Productor_Name()
{
    static int i = 0;
    i = i % PRODUCTOR_NUMBER + 1;
    char str[64];
    snprintf(str, sizeof(str), "Productor-%d", i++);
    return str;
}
std::string Consumer_Name()
{
    static int j = 0;
    j = j % CONSUER_NUMBER + 1;
    char str[64];
    snprintf(str, sizeof(str), "Consumer-%d", j++);
    return str;
}
// productor todo
void *Productor(void *args)
{
    std::string product_name =  Productor_Name();
    const char str[] = "+-*/%!#";
    QueueBlock<Task<int>> *que = static_cast<QueueBlock<Task<int>> *>(args);
    while (true)
    {
        int data1 = rand() % 10;
        int data2 = rand() % 10;
        char ch = str[rand() % strlen(str)];
        Task<int> t{data1, data2, ch};
        que->Push(t);
        std::cout << product_name << " send a task : "
                  << data1 << ch << data2
                  << "=?" << std::endl;
        sleep(1);
    }
}

// consumer todo
void *Consumer(void *args)
{
    std::string consumer_name = Consumer_Name();
    QueueBlock<Task<int>> *que = static_cast<QueueBlock<Task<int>> *>(args);
    while (true)
    {
        Task<int> t;
        que->Pop(&t);
        t.Run();
        std::cout << consumer_name << " get a task : "
                  << t._data1 << t._rule << t._data2 << "=" << t._result
                  << "[" << t._rerrno << "]" << std::endl;
    }
}

int main()
{
    srand(time(nullptr) ^ getpid() ^ pthread_self() ^ getppid());
    // 定义阻塞队列
    QueueBlock<Task<int>> *que = new QueueBlock<Task<int>>;

    // 创建生产者thread
    std::vector<pthread_t> productors(PRODUCTOR_NUMBER);
    for (auto &e : productors)
    {
        pthread_create(&e, nullptr, Productor, que);
    }

    // 创建消费者thread
    std::vector<pthread_t> consumers(CONSUER_NUMBER);
    for (auto &e : consumers)
    {
        pthread_create(&e, nullptr, Consumer, que);
    }

    // 等待生产者、消费者
    for (auto &e : productors)
    {
        pthread_join(e, nullptr);
    }

    for (auto &e : consumers)
    {
        pthread_join(e, nullptr);
    }
    return 0;
}